﻿
// SerialThreadDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "JointSerialTest.h"
#include "JointSerialTestDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CJointSerialTestDlg 对话框
CJointSerialTestDlg::CJointSerialTestDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_SERIALTHREAD_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	MDlg = NULL;
	SDlg = NULL;
	GDlg = NULL;
	PDlg = NULL;
	EDlg = NULL;
	RDlg = NULL;

	MGyro = new NavChart();
	MAcce = new NavChart();
	SGyro = new NavChart();
	SAcce = new NavChart();
}

CJointSerialTestDlg::~CJointSerialTestDlg()
{
	if (MDlg != NULL) {
		delete MDlg;
		MDlg = NULL;
	}

	if (SDlg != NULL) {
		delete SDlg;
		SDlg = NULL;
	}

	if (GDlg != NULL) {
		delete GDlg;
		GDlg = NULL;
	}

	if (PDlg != NULL) {
		delete PDlg;
		PDlg = NULL;
	}

	if (EDlg != NULL) {
		delete EDlg;
		EDlg = NULL;
	}

	if (RDlg != NULL) {
		delete RDlg;
		RDlg = NULL;
	}
}

void CJointSerialTestDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LED_S1, led_S1);
	DDX_Control(pDX, IDC_LED_S2, led_S2);
	DDX_Control(pDX, IDC_LED_S3, led_S3);
	DDX_Control(pDX, IDC_LED_S4, led_S4);
	DDX_Control(pDX, IDC_LED_S5, led_S5);
	DDX_Control(pDX, IDC_LED_SAVE, led_save);
	DDX_Control(pDX, IDC_BUTTON_COM_S1, btnMINS);
	DDX_Control(pDX, IDC_BUTTON_COM_S2, btnSINS);
	DDX_Control(pDX, IDC_BUTTON_COM_S3, btnGNSS);
	DDX_Control(pDX, IDC_BUTTON_COM_S4, btnPRE);
	DDX_Control(pDX, IDC_BUTTON_COM_S5, btnRTK);
	DDX_Control(pDX, IDC_COMBO_DEV_S1, ComboDevS1);
	DDX_Control(pDX, IDC_COMBO_DEV_S2, ComboDevS2);
	DDX_Control(pDX, IDC_COMBO_DEV_S3, ComboDevS3);
	DDX_Control(pDX, IDC_COMBO_DEV_S4, ComboDevS4);
	DDX_Control(pDX, IDC_COMBO_DEV_S5, ComboDevS5);
	DDX_Control(pDX, IDC_COMBO_COM_S1, ComboComS1);
	DDX_Control(pDX, IDC_COMBO_COM_S2, ComboComS2);
	DDX_Control(pDX, IDC_COMBO_COM_S3, ComboComS3);
	DDX_Control(pDX, IDC_COMBO_COM_S4, ComboComS4);
	DDX_Control(pDX, IDC_COMBO_COM_S5, ComboComS5);
	DDX_Control(pDX, IDC_COMBO_BDR_S1, ComboBdrS1);
	DDX_Control(pDX, IDC_COMBO_BDR_S2, ComboBdrS2);
	DDX_Control(pDX, IDC_COMBO_BDR_S3, ComboBdrS3);
	DDX_Control(pDX, IDC_COMBO_BDR_S4, ComboBdrS4);
	DDX_Control(pDX, IDC_COMBO_BDR_S5, ComboBdrS5);
	DDX_Control(pDX, IDC_COMBO_STP_S1, ComboStpS1);
	DDX_Control(pDX, IDC_COMBO_STP_S2, ComboStpS2);
	DDX_Control(pDX, IDC_COMBO_STP_S3, ComboStpS3);
	DDX_Control(pDX, IDC_COMBO_STP_S4, ComboStpS4);
	DDX_Control(pDX, IDC_COMBO_STP_S5, ComboStpS5);
	DDX_Control(pDX, IDC_COMBO_PRT_S1, ComboPrtS1);
	DDX_Control(pDX, IDC_COMBO_PRT_S2, ComboPrtS2);
	DDX_Control(pDX, IDC_COMBO_PRT_S3, ComboPrtS3);
	DDX_Control(pDX, IDC_COMBO_PRT_S4, ComboPrtS4);
	DDX_Control(pDX, IDC_COMBO_PRT_S5, ComboPrtS5);
	DDX_Control(pDX, IDC_EDIT_BOTTOM, stateDisp);
	DDX_Control(pDX, IDC_TIMER_DATE, TimerDate);
	DDX_Control(pDX, IDC_TIMER_TIME, TimerTime);
	DDX_Control(pDX, IDC_TIMER_CNTE, TimerCnte);
	DDX_Control(pDX, IDC_STATIC_DATE, textDate);
	DDX_Control(pDX, IDC_STATIC_TIME, textTime);
	DDX_Control(pDX, IDC_STATIC_CNTE, textCnte);
	DDX_Control(pDX, IDC_BUTTON_TIMERON, btnTimerOn);
	DDX_Control(pDX, IDC_BUTTON_TIMESET, btnTimerReset);
	DDX_Control(pDX, IDC_STATIC_MDEV, dispMDEV);
	DDX_Control(pDX, IDC_STATIC_MCNT, dispMCNT);
	DDX_Control(pDX, IDC_STATIC_MTEM, dispMTEM);
	DDX_Control(pDX, IDC_STATIC_MWX, dispMWX);
	DDX_Control(pDX, IDC_STATIC_MWY, dispMWY);
	DDX_Control(pDX, IDC_STATIC_MWZ, dispMWZ);
	DDX_Control(pDX, IDC_STATIC_MFX, dispMFX);
	DDX_Control(pDX, IDC_STATIC_MFY, dispMFY);
	DDX_Control(pDX, IDC_STATIC_MFZ, dispMFZ);
	DDX_Control(pDX, IDC_STATIC_SDEV, dispSDEV);
	DDX_Control(pDX, IDC_STATIC_SCNT, dispSCNT);
	DDX_Control(pDX, IDC_STATIC_STEM, dispSTEM);
	DDX_Control(pDX, IDC_STATIC_SWX, dispSWX);
	DDX_Control(pDX, IDC_STATIC_SWY, dispSWY);
	DDX_Control(pDX, IDC_STATIC_SWZ, dispSWZ);
	DDX_Control(pDX, IDC_STATIC_SFX, dispSFX);
	DDX_Control(pDX, IDC_STATIC_SFY, dispSFY);
	DDX_Control(pDX, IDC_STATIC_SFZ, dispSFZ);
	DDX_Control(pDX, IDC_STATIC_GTM, dispGTM);
	DDX_Control(pDX, IDC_STATIC_GNS, dispGNS);
	DDX_Control(pDX, IDC_STATIC_STYP, dispSTYP);
	DDX_Control(pDX, IDC_STATIC_DOP, dispDOP);
	DDX_Control(pDX, IDC_STATIC_GVF, dispGVF);
	DDX_Control(pDX, IDC_STATIC_GVU, dispGVU);
	DDX_Control(pDX, IDC_STATIC_YAW, dispYAW);
	DDX_Control(pDX, IDC_STATIC_LAT, dispLAT);
	DDX_Control(pDX, IDC_STATIC_LNT, dispLNT);
	DDX_Control(pDX, IDC_STATIC_ALT, dispALT);
	DDX_Control(pDX, IDC_CHART_MG, *MGyro);
	DDX_Control(pDX, IDC_CHART_MA, *MAcce);
	DDX_Control(pDX, IDC_CHART_SG, *SGyro);
	DDX_Control(pDX, IDC_CHART_SA, *SAcce);
	DDX_Control(pDX, IDC_BUTTON_DATASTORE, btn_store);
	DDX_Control(pDX, IDC_BUTTON_GRSWITCHER, GRSwitcher);
}

BEGIN_MESSAGE_MAP(CJointSerialTestDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BUTTON_COM_S4,		&CJointSerialTestDlg::OnBnClickedButtonComS4)
	ON_BN_CLICKED(IDC_BUTTON_COM_S1,		&CJointSerialTestDlg::OnBnClickedButtonComS1)
	ON_BN_CLICKED(IDC_BUTTON_COM_S2,		&CJointSerialTestDlg::OnBnClickedButtonComS2)
	ON_BN_CLICKED(IDC_BUTTON_COM_S3,		&CJointSerialTestDlg::OnBnClickedButtonComS3)
	ON_BN_CLICKED(IDC_BUTTON_COM_S5,		&CJointSerialTestDlg::OnBnClickedButtonComS5)
	ON_BN_CLICKED(IDC_BUTTON_TIMERON,	&CJointSerialTestDlg::OnBnClickedTimerStart)
	ON_BN_CLICKED(IDC_BUTTON_TIMESET,	&CJointSerialTestDlg::OnBnClickedTimerReset)
	ON_MESSAGE(THREAD_GET_MID,			&CJointSerialTestDlg::MIDDataProcess)
	ON_MESSAGE(THREAD_GET_SID,			&CJointSerialTestDlg::SIDDataProcess)
	ON_MESSAGE(THREAD_GET_GPO,			&CJointSerialTestDlg::GPODataProcess)
	ON_MESSAGE(THREAD_GET_GVE,			&CJointSerialTestDlg::GVEDataProcess)
	ON_MESSAGE(THREAD_GET_PPR,			&CJointSerialTestDlg::PPRDataProcess)
	ON_MESSAGE(THREAD_GET_PSP,			&CJointSerialTestDlg::PSPDataProcess)
	ON_MESSAGE(THREAD_GET_PEP,			&CJointSerialTestDlg::PEPDataProcess)
	ON_MESSAGE(THREAD_GET_RPO,			&CJointSerialTestDlg::RPODataProcess)
	ON_MESSAGE(THREAD_GET_RVE,			&CJointSerialTestDlg::RVEDataProcess)
	ON_MESSAGE(THREAD_ERR_NOP,			&CJointSerialTestDlg::SerialNotOpenPeocess)
	ON_COMMAND(ID_MSINSLIST,				&CJointSerialTestDlg::OnMsinslist)
	ON_COMMAND(ID_SINSLIST,				&CJointSerialTestDlg::OnSinslist)
	ON_COMMAND(ID_GNSSLIST,				&CJointSerialTestDlg::OnGnsslist)
	ON_COMMAND(ID_PREPLIST,				&CJointSerialTestDlg::OnPreplist)
	ON_COMMAND(ID_EPHMLIST,				&CJointSerialTestDlg::OnEphmlist)
	ON_COMMAND(ID_RTKGLIST,				&CJointSerialTestDlg::OnRtkglist)
	ON_BN_CLICKED(IDC_BUTTON2,			&CJointSerialTestDlg::OnDlgCloseBnClickedButton)
	ON_BN_CLICKED(IDC_BUTTON_DATASTORE, &CJointSerialTestDlg::OnBnClickedButtonDatastore)
	ON_BN_CLICKED(IDC_BUTTON_GRSWITCHER, &CJointSerialTestDlg::OnBnClickedButtonGrswitcher)
END_MESSAGE_MAP()


// CJointSerialTestDlg 消息处理程序

BOOL CJointSerialTestDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时，框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);			// 设置小图标

	// TODO: 在此添加额外的初始化代码
	LEDInit();		// LED初始化
	ComboInit();		// ComboBox初始化
	threadsInit();	// 串口初始化
	TimerInit();		// 计时器初始化
	datadispinit();	// 数据显示初始化
	chartsInit();	// 折线图初始化
	fileioinit();	//

	return TRUE;  // 除非将焦点设置到控件，否则返回 TRUE
}

// 如果向对话框添加最小化按钮，则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序，
//  这将由框架自动完成。

void CJointSerialTestDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CJointSerialTestDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CJointSerialTestDlg::LEDInit()
{
	led_S1.SetLed(CLed::LED_COLOR_GREY);
	led_S2.SetLed(CLed::LED_COLOR_GREY);
	led_S3.SetLed(CLed::LED_COLOR_GREY);
	led_S4.SetLed(CLed::LED_COLOR_GREY);
	led_S5.SetLed(CLed::LED_COLOR_GREY);
	led_save.SetLed(CLed::LED_COLOR_RED);
}

void CJointSerialTestDlg::ComboInit()
{
	CString ComX;
	CString bdr[10] = {L"2400", L"4800",  L"9600",  L"19200", L"38400",
					   L"57600",L"115200",L"230400",L"460800",L"921600"};
	CString stp[3] = { L"1",      L"1.5",    L"2"      };
	CString prt[3] = { L"无校验", L"奇校验", L"偶校验" };
	for (size_t i = 0; i <= 50; i++)
	{
		if (i==50)
			ComX.Format(L"COM%d", 0);
		else
			ComX.Format(L"COM%d", i + 1);
		ComboComS1.AddString(ComX);
		ComboComS2.AddString(ComX);
		ComboComS3.AddString(ComX);
		ComboComS4.AddString(ComX);
		ComboComS5.AddString(ComX);
	}

	for (size_t i = 0; i < 10; i++)
	{
		ComboBdrS1.AddString(bdr[i]);
		ComboBdrS2.AddString(bdr[i]);
		ComboBdrS3.AddString(bdr[i]);
		ComboBdrS4.AddString(bdr[i]);
		ComboBdrS5.AddString(bdr[i]);
	}

	for (size_t i = 0; i < 3; i++)
	{
		ComboStpS1.AddString(stp[i]);
		ComboStpS2.AddString(stp[i]);
		ComboStpS3.AddString(stp[i]);
		ComboStpS4.AddString(stp[i]);
		ComboStpS5.AddString(stp[i]);
		ComboPrtS1.AddString(prt[i]);
		ComboPrtS2.AddString(prt[i]);
		ComboPrtS3.AddString(prt[i]);
		ComboPrtS4.AddString(prt[i]);
		ComboPrtS5.AddString(prt[i]);
	}

	// 选中初始选项
	ComboDevS1.SetCurSel(0);		// 0:哈工程		1:〇光纤惯导		3:STIM300	4:PSINS开发板
	ComboDevS2.SetCurSel(2);		// 0:哈工程		1:〇光纤惯导		3:STIM300	4:PSINS开发板
	ComboDevS3.SetCurSel(0);		// 0:C201		1:NC540
	ComboDevS4.SetCurSel(1);		// 0:C201		1:NC540
	ComboDevS5.SetCurSel(0);		// 0:C201		1:NC540

	ComboComS1.SetCurSel(0);
	ComboComS2.SetCurSel(1);
	ComboComS3.SetCurSel(2);
	ComboComS4.SetCurSel(3);
	ComboComS5.SetCurSel(4);

	ComboBdrS1.SetCurSel(6);		// 115200
	ComboBdrS2.SetCurSel(6);
	ComboBdrS3.SetCurSel(6);
	ComboBdrS4.SetCurSel(6);
	ComboBdrS5.SetCurSel(6);

	ComboStpS1.SetCurSel(0);		// 1bit 停止位
	ComboStpS2.SetCurSel(0);
	ComboStpS3.SetCurSel(0);
	ComboStpS4.SetCurSel(0);
	ComboStpS5.SetCurSel(0);

	ComboPrtS1.SetCurSel(0);	// 无校验
	ComboPrtS2.SetCurSel(0);
	ComboPrtS3.SetCurSel(0);
	ComboPrtS4.SetCurSel(0);
	ComboPrtS5.SetCurSel(0);
}

/********************************************************************/
/*		计时器初始化函数											*/
/********************************************************************/
void CJointSerialTestDlg::TimerInit()
{
	titleFont.CreateFont(32, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
			OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PALETTE, L"system");
	textDate.SetFont(&titleFont);
	textTime.SetFont(&titleFont);
	textCnte.SetFont(&titleFont);
	TimerCnte.SetText(_T("00000"));

	/* 
	*   定时器设置
	*	有两个定时器，一个更新系统时间，一个作为定时器
	*/
	SetLocalTime();
	SetTimer(1, 1000, 0);		// 系统时间更新	
}

void CJointSerialTestDlg::SetLocalTime()
{
	CString time_tmp;
	GetLocalTime(&st);
	time_tmp.Format(_T("%4d-%02d-%02d"), st.wYear, st.wMonth, st.wDay);
	TimerDate.SetText(time_tmp);
	time_tmp.Format(_T("%02d:%02d:%02d"), st.wHour, st.wMinute, st.wSecond);
	TimerTime.SetText(time_tmp);
}

void CJointSerialTestDlg::OnTimer(UINT_PTR nIDEvent)
{
	CString time_tmp;
	switch (nIDEvent)
	{
	case 1:
		SetLocalTime();
		break;
	case 2:
		if (counterPause)
		{
			time_tmp.Format(L"%5d", ++secCounter);		// 修改secCounter为UINT（2021-05-24）
			TimerCnte.SetText(time_tmp);
		}
		break;
	}
	CDialogEx::OnTimer(nIDEvent);
}

void CJointSerialTestDlg::OnBnClickedTimerStart()
{
	counterPause = !counterPause;
	if (counterPause) {
		btnTimerOn.SetWindowText(_T("暂停计时"));
		SetTimer(2, 1000, 0);		// 采样时间更新
	}
	else {
		btnTimerOn.SetWindowText(_T("开始计时"));
		KillTimer(2);
	}
}

void CJointSerialTestDlg::OnBnClickedTimerReset()
{
	CString time_tmp;
	secCounter = 0;
	time_tmp.Format(_T("%5d"), secCounter);
	TimerCnte.SetText(time_tmp);
}

/********************************************************************/
/*		串口线程初始化函数											*/
/********************************************************************/
void CJointSerialTestDlg::threadsInit()
{
	serialMag = new SerialThreadManager(AfxGetMainWnd()->m_hWnd);
	thdMINS = new SerialThread();
	thdSINS = new SerialThread();
	thdGNSS = new SerialThread();
	thdPDE  = new SerialThread();
	thdRTK  = new SerialThread();

	serialMag->lppara[0].ST = thdMINS;
	serialMag->lppara[1].ST = thdSINS;
	serialMag->lppara[2].ST = thdGNSS;
	serialMag->lppara[3].ST = thdPDE;
	serialMag->lppara[4].ST = thdRTK;
}

/********************************************************************/
/*		未打开警告回调函数											*/
/********************************************************************/
LRESULT CJointSerialTestDlg::SerialNotOpenPeocess(WPARAM wParam, LPARAM lParam)
{
	CString cont;
	serialMag->threadon[wParam] = FALSE;
	switch (wParam)
	{
	case 0:
		btnMINS.SetWindowTextW(L"打开串口");
		led_S1.SetLed(CLed::LED_COLOR_GREY);
		break;
	case 1:
		btnSINS.SetWindowTextW(L"打开串口");
		led_S2.SetLed(CLed::LED_COLOR_GREY);
		break;
	case 2:
		btnGNSS.SetWindowTextW(L"打开串口");
		led_S3.SetLed(CLed::LED_COLOR_GREY);
		break;
	case 3:
		btnPRE.SetWindowTextW(L"打开串口");
		led_S4.SetLed(CLed::LED_COLOR_GREY);
		break;
	case 4:
		btnRTK.SetWindowTextW(L"打开串口");
		led_S5.SetLed(CLed::LED_COLOR_GREY);
		break;
	default:
		break;
	}
	cont.Format(L"%s打开失败！", errMBcont[wParam].GetString(),20);
	MessageBox(cont, TEXT("警告"), MB_OK);
	return LRESULT();
}

/********************************************************************/
/*		数据解析回调函数												*/
/********************************************************************/
LRESULT CJointSerialTestDlg::MIDDataProcess(WPARAM wParam, LPARAM lParam)
{
	/*CString state;*/
	syscnt_mins++;
	// 获取精确时间
	if (isStoring == TRUE)
	{
		syscnt_ms[0] = (UINT)wParam;
		// syscnt_ms[0] = syscnt_mins;
		// TRACE(L"主惯导采样时间：%d\n", syscnt_ms[0]);
	}
	memcpy(serialDataBuffer[0], thdMINS->buffer, thdMINS->pkglen);
	serialDataProc(thdMINS->device, serialDataBuffer[0], &Mimudata);

	if (isStoring==TRUE)
	{
		ns.StoreinThread(MINS, syscnt_ms[0], syscnt_mins, &Mimudata, NULL);
		/*state.Format(L"%d", ns.MINSBuffer.getLen());
		stateDisp.SetWindowTextW(state);*/
		
	}
	if (syscnt_mins % thdMINS->fps == 0)
	{
		addMIMUData();
		if (MDlg != NULL)
			SendMessageA(MDlg->m_hWnd, LISTMSG_GETMINS, (WPARAM)&Mimudata, NULL);

		DOUBLE txyzg[4] = {	syscnt_mins * (double)thdMINS->ts,
							Mimudata.wx,
							Mimudata.wy,
							Mimudata.wz };
		MGyro->addSample(txyzg);
		DOUBLE txyza[4] = { syscnt_mins * (double)thdMINS->ts,
							Mimudata.fx,
							Mimudata.fy,
							Mimudata.fz };
		MAcce->addSample(txyza);
	}
	return LRESULT();
}

LRESULT CJointSerialTestDlg::SIDDataProcess(WPARAM wParam, LPARAM lParam)
{
	// 获取精确时间
	if (isStoring == TRUE)
	{
		syscnt_ms[1] = (UINT)wParam;
		//syscnt_ms[1] = syscnt_mins;
		//TRACE(L"子惯导采样时间：%d\n", syscnt_ms[1]);
	}
	memcpy(serialDataBuffer[1], thdSINS->buffer, thdSINS->pkglen);
	serialDataProc(thdSINS->device, serialDataBuffer[1], &Simudata);
	syscnt_sins++;
	if (isStoring == TRUE)
	{
		ns.StoreinThread(SINS, syscnt_ms[1], syscnt_sins, &Simudata, NULL);
	}
	if (syscnt_sins % thdSINS->fps == 0)
	{
		addSIMUData();
		if (SDlg != NULL)
			SendMessageA(SDlg->m_hWnd, LISTMSG_GETSINS, (WPARAM)&Simudata, NULL);

		DOUBLE txyzg[4] = { syscnt_sins * (double)thdSINS->ts,
							Simudata.wx,
							Simudata.wy,
							Simudata.wz };
		SGyro->addSample(txyzg);
		DOUBLE txyza[4] = { syscnt_sins * (double)thdSINS->ts,
							Simudata.fx,
							Simudata.fy,
							Simudata.fz };
		SAcce->addSample(txyza);
	}
	return LRESULT();
}

/*
* 无论指令顺序如何，都是先速度后位置
* 所以在位置更新后，加入文件保存既可
*/
LRESULT CJointSerialTestDlg::GPODataProcess(WPARAM wParam, LPARAM lParam)
{
	// 获取精确时间
	if (isStoring == TRUE)
	{
		syscnt_ms[2] = (UINT)wParam;
		//syscnt_ms[2] = syscnt_mins;
		//TRACE(L"GNSS采样时间：%d\n", syscnt_ms[2]);
	}
	memcpy(serialDataBuffer[2], thdGNSS->buffer, thdGNSS->GNSSpkglen);
	serialDataProc(thdGNSS->device, serialDataBuffer[2], &GNSSpos);
	syscnt_gnss++;
	if (isStoring == TRUE)
	{
		ns.StoreinThread(GNSS, syscnt_ms[2], syscnt_gnss, &GNSSpos, &GNSSvel);
	}
	if (RTKon == FALSE)		// 开关关闭则显示GNSS数据
		addGNSSData();		// 显示
	return LRESULT();
}

LRESULT CJointSerialTestDlg::GVEDataProcess(WPARAM wParam, LPARAM lParam)
{
	memcpy(serialDataBuffer[3], thdGNSS->buffer, thdGNSS->GNSSpkglen);
	serialDataProc(thdGNSS->device, serialDataBuffer[3], &GNSSvel);
	//addGNSSData();			// 因为速度先到，所以收到位置后更新列表
	if (GDlg != NULL)		// 速度数据更新后更新列表数据
		SendMessageA(GDlg->m_hWnd, LISTMSG_GETGNSS, (WPARAM)&GNSSpos, (LPARAM)&GNSSvel);
	return LRESULT();
}

LRESULT CJointSerialTestDlg::PPRDataProcess(WPARAM wParam, LPARAM lParam)
{
	// 获取精确时间
	if (isStoring == TRUE)
	{
		syscnt_ms[3] = (UINT)wParam;
		//syscnt_ms[3] = syscnt_mins;
		//TRACE(L"伪距星历采样时间：%d\n", syscnt_ms[3]);
	}
	memcpy(serialDataBuffer[4], thdPDE->buffer, thdPDE->GNSSpkglen);
	serialDataProc(serialDataBuffer[4], &rngtab);
	syscnt_pre++;
	if (EPHReady == TRUE)
	{
		if (EDlg != NULL)		// 速度数据更新后书更新列表数据
			SendMessageA(EDlg->m_hWnd, LISTMSG_GETEPHM, (WPARAM)&ephtab, NULL);
		if (isStoring == TRUE)
		{
			ns.StoreinThread(EPH, syscnt_ms[3], syscnt_pre, &ephtab, NULL);
		}
		EPHReady = FALSE;
	}
	if (isStoring == TRUE)
	{
		ns.StoreinThread(PSR, syscnt_ms[3], syscnt_pre, &rngtab, NULL);
	}
	if (PDlg != NULL)		// 速度数据更新后书更新列表数据
		SendMessageA(PDlg->m_hWnd, LISTMSG_GETPRNG, (WPARAM)&rngtab, NULL);
	return LRESULT();
}

LRESULT CJointSerialTestDlg::PSPDataProcess(WPARAM wParam, LPARAM lParam)
{
	memcpy(serialDataBuffer[5], thdPDE->buffer, thdPDE->GNSSpkglen);
	serialDataProc(serialDataBuffer[5], &sattab);
	if (isStoring == TRUE)
	{
		ns.StoreinThread(STP, syscnt_ms[3], syscnt_pre, &sattab, NULL);
	}
	return LRESULT();
}

LRESULT CJointSerialTestDlg::PEPDataProcess(WPARAM wParam, LPARAM lParam)
{
	memcpy(serialDataBuffer[6], thdPDE->buffer, thdPDE->GNSSpkglen);
	serialDataProc(serialDataBuffer[6], &ephtab);
	EPHReady = TRUE;			// 星历数据在伪距数据处理中保存
	return LRESULT();
}

LRESULT CJointSerialTestDlg::RPODataProcess(WPARAM wParam, LPARAM lParam)
{
	// 获取精确时间
	if (isStoring == TRUE)
	{
		syscnt_ms[4] = (UINT)wParam;
		//syscnt_ms[4] = syscnt_mins;
		//TRACE(L"RTK采样时间：%d\n", syscnt_ms[4]);
	}
	memcpy(serialDataBuffer[7], thdRTK->buffer, thdRTK->GNSSpkglen);
	serialDataProc(thdRTK->device, serialDataBuffer[7], &RTKpos);
	syscnt_rtk++;
	if (isStoring == TRUE)
	{
		ns.StoreinThread(RTKG, syscnt_ms[4], syscnt_rtk, &RTKpos, &RTKvel);
	}
	if (RTKon == TRUE)		// 开关打开则显示RTK数据
		addRTKGData();
	if (RDlg != NULL)		// 位置数据更新后书更新列表数据
		SendMessageA(RDlg->m_hWnd, LISTMSG_GETRTKG, (WPARAM)&RTKpos, (LPARAM)&RTKvel);
	return LRESULT();
}

LRESULT CJointSerialTestDlg::RVEDataProcess(WPARAM wParam, LPARAM lParam)
{
	memcpy(serialDataBuffer[8], thdRTK->buffer, thdRTK->GNSSpkglen);
	serialDataProc(thdRTK->device, serialDataBuffer[8], &RTKvel);
	return LRESULT();
}


/********************************************************************/
/*		数据显示操作函数												*/
/********************************************************************/
void CJointSerialTestDlg::datadispinit()
{
	dispMDEV.SetText(L"0");
	dispMCNT.SetText(L"0");
	dispMTEM.SetText(L"0");
	dispMWX.SetText(L"0");
	dispMWY.SetText(L"0");
	dispMWZ.SetText(L"0");
	dispMFX.SetText(L"0");
	dispMFY.SetText(L"0");
	dispMFZ.SetText(L"0");
	dispSDEV.SetText(L"0");
	dispSCNT.SetText(L"0");
	dispSTEM.SetText(L"0");
	dispSWX.SetText(L"0");
	dispSWY.SetText(L"0");
	dispSWZ.SetText(L"0");
	dispSFX.SetText(L"0");
	dispSFY.SetText(L"0");
	dispSFZ.SetText(L"0");
	dispGTM.SetText(L"0");
	dispGNS.SetText(L"0");
	dispDOP.SetText(L"0");
	dispSTYP.SetText(L"0");
	dispGVF.SetText(L"0");
	dispGVU.SetText(L"0");
	dispYAW.SetText(L"0");
	dispLAT.SetText(L"0");
	dispLNT.SetText(L"0");
	dispALT.SetText(L"0");
}

void CJointSerialTestDlg::addMIMUData()
{
	CString data;
	data.Format(L"%8d", thdMINS->device);
	dispMDEV.SetText(data);
	data.Format(L"%8d", Mimudata.CNT);
	dispMCNT.SetText(data);
	data.Format(L"%8d", Mimudata.Tp1);
	dispMTEM.SetText(data);
	data.Format(L"%9.4f", Mimudata.wx);
	dispMWX.SetText(data);
	data.Format(L"%9.4f", Mimudata.wy);
	dispMWY.SetText(data);
	data.Format(L"%9.4f", Mimudata.wz);
	dispMWZ.SetText(data);
	data.Format(L"%9.4f", Mimudata.fx);
	dispMFX.SetText(data);
	data.Format(L"%9.4f", Mimudata.fy);
	dispMFY.SetText(data);
	data.Format(L"%9.4f", Mimudata.fz);
	dispMFZ.SetText(data);
}

void CJointSerialTestDlg::addSIMUData()
{
	CString data;
	data.Format(L"%8d", thdSINS->device);
	dispSDEV.SetText(data);
	data.Format(L"%8d", Simudata.CNT);
	dispSCNT.SetText(data);
	data.Format(L"%8d", Simudata.Tp1);
	dispSTEM.SetText(data);
	data.Format(L"%9.4f", Simudata.wx);
	dispSWX.SetText(data);
	data.Format(L"%9.4f", Simudata.wy);
	dispSWY.SetText(data);
	data.Format(L"%9.4f", Simudata.wz);
	dispSWZ.SetText(data);
	data.Format(L"%9.4f", Simudata.fx);
	dispSFX.SetText(data);
	data.Format(L"%9.4f", Simudata.fy);
	dispSFY.SetText(data);
	data.Format(L"%9.4f", Simudata.fz);
	dispSFZ.SetText(data);
}

void CJointSerialTestDlg::addGNSSData()
{
	CString data;
	data.Format(L"%8d", GNSSvel.ph.second);
	dispGTM.SetText(data);
	data.Format(L"%2d", GNSSpos.SatNum);
	dispGNS.SetText(data);
	data.Format(L"%1d", GNSSpos.state);
	dispSTYP.SetText(data);
	data.Format(L"%3.1f", GNSSpos.HDOP);
	dispDOP.SetText(data);
	data.Format(L"%9.4f", GNSSvel.vel_h);
	dispGVF.SetText(data);
	data.Format(L"%9.4f", GNSSvel.vel_v);
	dispGVU.SetText(data);
	data.Format(L"%9.4f", GNSSvel.heading);
	dispYAW.SetText(data);
	data.Format(L"%9.4f", GNSSpos.Lat);
	dispLAT.SetText(data);
	data.Format(L"%9.4f", GNSSpos.Lng);
	dispLNT.SetText(data);
	data.Format(L"%9.4f", GNSSpos.Alt);
	dispALT.SetText(data);
}

void CJointSerialTestDlg::addRTKGData()
{
	CString data;
	data.Format(L"%8d", RTKvel.ph.second);
	dispGTM.SetText(data);
	data.Format(L"%2d", RTKpos.SatNum);
	dispGNS.SetText(data);
	data.Format(L"%1d", RTKpos.state);
	dispSTYP.SetText(data);
	data.Format(L"%3.1f", RTKpos.HDOP);
	dispDOP.SetText(data);
	data.Format(L"%9.4f", RTKvel.vel_h);
	dispGVF.SetText(data);
	data.Format(L"%9.4f", RTKvel.vel_v);
	dispGVU.SetText(data);
	data.Format(L"%9.4f", RTKvel.heading);
	dispYAW.SetText(data);
	data.Format(L"%9.4f", RTKpos.Lat);
	dispLAT.SetText(data);
	data.Format(L"%9.4f", RTKpos.Lng);
	dispLNT.SetText(data);
	data.Format(L"%9.4f", RTKpos.Alt);
	dispALT.SetText(data);
}


/********************************************************************/
/*		串口开关回调函数												*/
/********************************************************************/
void CJointSerialTestDlg::OnBnClickedButtonComS1()
{
	if (serialMag->threadon[0] == FALSE)
	{
		thdMINS->setIMUDevice((DeviceID)ComboDevS1.GetCurSel());
		thdMINS->setPortName(ComboComS1.GetCurSel());
		thdMINS->setBaudrate(bdrlist[ComboBdrS1.GetCurSel()]);
		thdMINS->setStopbit(0);
		thdMINS->setParity(0);
		thdMINS->ts = (FLOAT)1.0 / imuFs[ComboDevS1.GetCurSel()];
		thdMINS->fps = imuFs[(INT)thdMINS->device] / 5;
		serialMag->threadon[0] = TRUE;
		serialMag->startComm(0);
		btnMINS.SetWindowTextW(L"关闭串口");
		led_S1.SetLed(CLed::LED_COLOR_GREEN);
	}
	else
	{
		//serialMag->threadon[0] = FALSE;
		serialMag->stopComm(0);
		btnMINS.SetWindowTextW(L"打开串口");
		led_S1.SetLed(CLed::LED_COLOR_GREY);
	}
}

void CJointSerialTestDlg::OnBnClickedButtonComS2()
{
	if (serialMag->threadon[1] == FALSE)
	{
		thdSINS->setIMUDevice((DeviceID)ComboDevS2.GetCurSel());
		thdSINS->setPortName(ComboComS2.GetCurSel());
		thdSINS->setBaudrate(bdrlist[ComboBdrS2.GetCurSel()]);
		thdSINS->setStopbit(0);
		thdSINS->setParity(0);
		thdSINS->ts = (FLOAT)1.0 / imuFs[ComboDevS2.GetCurSel()];
		thdSINS->fps = imuFs[(INT)thdSINS->device] / 5;
		serialMag->threadon[1] = TRUE;
		serialMag->startComm(1);
		btnSINS.SetWindowTextW(L"关闭串口");
		led_S2.SetLed(CLed::LED_COLOR_GREEN);
	}
	else
	{
		//serialMag->threadon[1] = FALSE;
		serialMag->stopComm(1);
		btnSINS.SetWindowTextW(L"打开串口");
		led_S2.SetLed(CLed::LED_COLOR_GREY);
	}
}

void CJointSerialTestDlg::OnBnClickedButtonComS3()
{
	if (serialMag->threadon[2] == FALSE)
	{
		thdGNSS->setGNSSDevice((DeviceID)(ComboDevS3.GetCurSel()+5), GNSSTask::SP);
		thdGNSS->setPortName(ComboComS3.GetCurSel());
		thdGNSS->setBaudrate(bdrlist[ComboBdrS3.GetCurSel()]);
		thdGNSS->setStopbit(0);
		thdGNSS->setParity(0);
		serialMag->threadon[2] = TRUE;
		serialMag->startComm(2);
		btnGNSS.SetWindowTextW(L"关闭串口");
		led_S3.SetLed(CLed::LED_COLOR_GREEN);
	}
	else
	{
		//serialMag->threadon[2] = FALSE;
		serialMag->stopComm(2);
		btnGNSS.SetWindowTextW(L"打开串口");
		led_S3.SetLed(CLed::LED_COLOR_GREY);
	}
}

void CJointSerialTestDlg::OnBnClickedButtonComS4()
{
	if (serialMag->threadon[3] == FALSE)
	{
		thdPDE->setGNSSDevice((DeviceID)(ComboDevS4.GetCurSel() + 5), GNSSTask::TI);
		thdPDE->setPortName(ComboComS4.GetCurSel());
		thdPDE->setBaudrate(bdrlist[ComboBdrS4.GetCurSel()]);
		thdPDE->setStopbit(ComboStpS4.GetCurSel());
		thdPDE->setParity(ComboPrtS4.GetCurSel());
		serialMag->threadon[3] = TRUE;
		serialMag->startComm(3);
		btnPRE.SetWindowTextW(L"关闭串口");
		led_S4.SetLed(CLed::LED_COLOR_GREEN);
	}
	else
	{
		//serialMag->threadon[3] = FALSE;
		serialMag->stopComm(3);
		btnPRE.SetWindowTextW(L"打开串口");
		led_S4.SetLed(CLed::LED_COLOR_GREY);
	}
}

void CJointSerialTestDlg::OnBnClickedButtonComS5()
{
	if (serialMag->threadon[4] == FALSE)
	{
		thdRTK->setGNSSDevice((DeviceID)(ComboDevS5.GetCurSel() + 5), GNSSTask::RTK);
		thdRTK->setPortName(ComboComS5.GetCurSel());
		thdRTK->setBaudrate(bdrlist[ComboBdrS5.GetCurSel()]);
		thdRTK->setStopbit(ComboStpS5.GetCurSel());
		thdRTK->setParity(ComboPrtS5.GetCurSel());
		serialMag->threadon[4] = TRUE;
		serialMag->startComm(4);
		btnRTK.SetWindowTextW(L"关闭串口");
		led_S5.SetLed(CLed::LED_COLOR_GREEN);
	}
	else
	{
		//serialMag->threadon[4] = FALSE;
		serialMag->stopComm(4);
		btnRTK.SetWindowTextW(L"打开串口");
		led_S5.SetLed(CLed::LED_COLOR_GREY);
	}
}
/********************************************************************/


/********************************************************************/
/*		菜单打开数据列表回调函数										*/
/********************************************************************/
void CJointSerialTestDlg::OnMsinslist()
{
	if (MDlg == NULL)
	{
		MDlg = new MinsListDlg();
		MDlg->Create(IDD_DIALOG_MINSLIST);
	}
	MDlg->ShowWindow(SW_SHOW);
}


void CJointSerialTestDlg::OnSinslist()
{
	if (SDlg == NULL)
	{
		SDlg = new SinsListDlg();
		SDlg->Create(IDD_DIALOG_SINSLIST);
	}
	SDlg->ShowWindow(SW_SHOW);
}


void CJointSerialTestDlg::OnGnsslist()
{
	if (GDlg == NULL)
	{
		GDlg = new GNSSListDlg();
		GDlg->Create(IDD_DIALOG_GNSSLIST);
	}
	GDlg->ShowWindow(SW_SHOW);
}


void CJointSerialTestDlg::OnPreplist()
{
	if (PDlg == NULL)
	{
		PDlg = new PRngListDlg();
		PDlg->Create(IDD_DIALOG_PREPLIST);
	}
	PDlg->ShowWindow(SW_SHOW);
}

void CJointSerialTestDlg::OnEphmlist()
{
	if (EDlg == NULL)
	{
		EDlg = new EphmListDlg();
		EDlg->Create(IDD_DIALOG_EPHMLIST);
	}
	EDlg->ShowWindow(SW_SHOW);
}


void CJointSerialTestDlg::OnRtkglist()
{
	if (RDlg == NULL)
	{
		RDlg = new RTKGListDlg();
		RDlg->Create(IDD_DIALOG_RTKGLIST);
	}
	RDlg->ShowWindow(SW_SHOW);
}
/********************************************************************/

/********************************************************************/
/*		Charts 初始化												*/
/********************************************************************/
void CJointSerialTestDlg::chartsInit()
{
	MGyro->init(L"角速度 deg/s", 100);
	MAcce->init(L"加速度 m/s^2", 100);
	SGyro->init(L"角速度 deg/s", 100);
	SAcce->init(L"加速度 m/s^2", 100);
}

/********************************************************************/
/*		关闭对话框按钮												*/
/********************************************************************/
void CJointSerialTestDlg::OnDlgCloseBnClickedButton()
{
	if (serialMag->threadon[0] + serialMag->threadon[1] + serialMag->threadon[2] +
		serialMag->threadon[3] + serialMag->threadon[4] == 0)
	{
		EndDialog(0);
		PostMessage(WM_CLOSE);
	}
	else
	{
		MessageBox(L"串口采数中，请先关闭全部串口！", TEXT("警告"), MB_OK);
	}
	
}

void CJointSerialTestDlg::fileioinit()
{
	for (size_t i = 0; i < 5; i++)
	{
		ns.isStoring[i] = FALSE;
	}
}

/********************************************************************/
/*		数据存储按钮												*/
/********************************************************************/
void CJointSerialTestDlg::OnBnClickedButtonDatastore()
{
	if (isStoring==FALSE)
	{
		if (!ns.NavStoreInit(&this->st))
		{
			MessageBox(L"警告",TEXT("文件打开失败，无法保存数据！"), MB_ICONERROR);
			return;
		}
		btn_store.SetWindowTextW(L"停止保存");
		isStoring = TRUE;
		led_save.SetLed(CLed::LED_COLOR_BLUE);
		for (size_t i = 0; i < 5; i++)
		{
			syscnt_ms[i] = 0;			// receive micro-second counter set zero.
		}
		//SetTimer(3, 1, 0);		// ms时间更新	ms定时器并不精确-->删除，改用HRTimer
	}
	else
	{
		MessageBox(L"串口采数中，确认停止保存数据?", TEXT("警告"), MB_OKCANCEL);
		ns.NavStoreStop();
		btn_store.SetWindowTextW(L"开始保存");
		isStoring = FALSE;
		led_save.SetLed(CLed::LED_COLOR_RED);
		//KillTimer(3);
	}
}

/********************************************************************/
/*		GNSS显示切换按钮												*/
/********************************************************************/
void CJointSerialTestDlg::OnBnClickedButtonGrswitcher()
{
	if ((!RTKon) && serialMag->threadon[4])
	{
		GRSwitcher.SetWindowTextW(L"RTK");
		RTKon = TRUE;
	}
	else
	{
		GRSwitcher.SetWindowTextW(L"GNSS");
		RTKon = FALSE;
	}
}
